
struct TFILESEC
{
 static CString pairDescs[2];
 static LPCWSTR tripleDescs[3];
 static void Init();

//	no file, ANSI code page or CP_UTF8, UNICODE
	unsigned m_nState;
	DWORD	 m_nSize;
	unsigned m_nCount;
	DWORD	 m_nMem;
	WCHAR	 m_cBOM;

	TFILESEC() { ::memset(this, 0, sizeof(TFILESEC)); }
	TFILESEC(const TFILESEC & aval) { ::memcpy(this, & aval, sizeof(TFILESEC)); }
//	op target: ANSI or UNICODE
	void beforeOpen(bool adouble) 
	{ 
		m_nState = (adouble) ? 2 : 1;
		m_cBOM = 0;
	}

//	attr
 inline LPCWSTR getDesc() const { return pairDescs[((m_nState) ? 1 : 0)]; }
 inline bool isUnicode() const { return (m_nState > 1); }
 inline BOOL isFile() const { return m_nState; }
 inline LPCWSTR getCodePage() const { 
	 unsigned i(m_nState); return tripleDescs[ ((i > 2)? 2 : i) ]; }
};

struct TCSVLINE
{
	//	in other words: '"'
	static const WCHAR	QUOTES = '\x22';
	static const WCHAR	COMMENT = ';';
	static LPCWSTR szTrimChars;
	static LPCWSTR szQuoteApos;
	static const unsigned COL_COUNT = 5;
 typedef int (CALLBACK * TPROC_CMP) (LPARAM, LPARAM, LPARAM);
	static const TPROC_CMP	VEC_CMP_PROC[3];

 static int CALLBACK CmpProcAsc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
 static int CALLBACK CmpProcDesc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
 static bool testSec(const CString & astr, CString & aname);
 static int dequotes(const CString & asource, LPCWSTR adelimit);
 static CString decorate(CString & astr)
 {
	 astr.Trim(szTrimChars);
	 if (!(astr.IsEmpty()))
		if (astr.GetAt(0) != QUOTES) 
			if (astr.Find(',') + 1) 
		{
			CString thestr;
				thestr.Format(L"\"%s\"", astr);
			return thestr;
		}

	return astr; 
 }

	explicit TCSVLINE(LPCWSTR asec = NULL) : 
		m_type(0), m_sec(asec), m_code(0) {}
	TCSVLINE(const TCSVLINE & aline);

 	//	name = value
	bool loadAttr(const CString & asource);

	//	comma-separated value
	bool loadTag(const CString & asource);

 inline LPCWSTR getSubItem(unsigned apos) { return m_vec[apos].operator LPCWSTR(); }
 inline bool isReg() const { return !(m_root.IsEmpty()); }
 inline unsigned getType() const { return m_type; }
 inline LPCWSTR getSec() const { return m_sec; }
 inline bool getPair(CString & aname, CString & aval) const
	{
		if (m_type) return false;
		if ((* m_vec).IsEmpty()) return false;

		aname = * m_vec; aval = m_vec[1];

		return true;
	}

	unsigned m_type;
	CString	m_sec;
	CString	m_root;
	CString m_vec[COL_COUNT + 2];
/*	CString	m_path;
	CString	m_name;
	CString	m_value;
	CString	m_tail;	*/
	DWORD	m_code;
};

typedef TCSVLINE * LPCSVLINE;
typedef TFILESEC * LPFILESEC;

namespace cmn {
	const LPFILESEC getFileSect();
	void ClipboardCopyText(const CString& text);
	bool CommonTrackMenu(CWnd* pWnd, const POINT & apoint, int subindex);
}
